home *** CD-ROM | disk | FTP | other *** search
/ The Very Best of Atari Inside / The Very Best of Atari Inside 1.iso / mint / mntlb20 / lib / _divmods.s < prev    next >
Text File  |  1990-04-03  |  3KB  |  94 lines

  1. | long division and modulus routines
  2. |
  3. | written by Kai-Uwe Bloem (I5110401@dbstu1.bitnet).
  4. |
  5. |
  6. | Revision 1.1, kub 03-90
  7. | first version, replaces the appropriate routine from fixnum.s.
  8. | Should be faster in more common cases. Division is done by 68000 divu
  9. | operations if divisor is only 16 bits wide. Otherwise the normal division
  10. | algorithm as described in various papers takes place. The division routine
  11. | delivers the quotient in d0 and the remainder in d1, thus the implementation
  12. | of the modulo operation is trivial. We gain some extra speed by inlining
  13. | the division code here instead of calling __udivsi3.
  14.  
  15.     .text
  16.     .even
  17.     .globl    __divsi3, ___divsi3
  18.     .globl    __modsi3, ___modsi3
  19.  
  20. __divsi3:
  21. ___divsi3:
  22.     movel    d2,a0        | save registers
  23.     movel    d3,a1
  24.     clrw    sp@-        | sign flag
  25.     clrl    d0        | prepare result
  26.     movel    sp@(10),d2    | get divisor
  27.     beq    9f        | divisor = 0 causes a division trap
  28.     bpl    0f        | divisor < 0 ?
  29.     negl    d2        | negate it
  30.     notw    sp@        | remember sign
  31. 0:    movel    sp@(6),d1    | get dividend
  32.     bpl    0f        | dividend < 0 ?
  33.     negl    d1        | negate it
  34.     notw    sp@        | remember sign
  35. 0:
  36. |== case 1) divident < divisor
  37.     cmpl    d2,d1        | is divident smaller then divisor ?
  38.     bcs    8f        | yes, return immediately
  39. |== case 2) divisor has <= 16 significant bits
  40.     tstw    sp@(10)
  41.     bne    2f        | divisor has only 16 bits
  42.     movew    d1,d3        | save dividend
  43.     clrw    d1        | divide dvd.h by dvs
  44.     swap    d1
  45.     beq    0f        | (no division necessary if dividend zero)
  46.     divu    d2,d1
  47. 0:    movew    d1,d0        | save quotient.h
  48.     swap    d0
  49.     movew    d3,d1        | (d0.h = remainder of prev divu)
  50.     divu    d2,d1        | divide dvd.l by dvs
  51.     movew    d1,d0        | save quotient.l
  52.     clrw    d1        | get remainder
  53.     swap    d1
  54.     bra    8f        | and return
  55. |== case 3) divisor > 16 bits (corollary is dividend > 16 bits, see case 1)
  56. 2:
  57.     moveq    #31,d3        | loop count
  58. 3:
  59.     addl    d1,d1        | shift divident ...
  60.     addxl    d0,d0        |  ... into d0
  61.     cmpl    d2,d0        | compare with divisor
  62.     bcs    0f
  63.     subl    d2,d0        | big enough, subtract
  64.     addw    #1,d1        | and note bit into result
  65. 0:
  66.     dbra    d3,3b
  67.     exg    d0,d1        | put quotient and remainder in their registers
  68. 8:
  69.     tstw    sp@(6)        | must the remainder be corrected ?
  70.     bpl    0f
  71.     negl    d1        | yes, apply sign
  72. | the following line would be correct if modulus is defined as in algebra
  73. |    addl    sp@(6),d1    | algebraic correction: modulus can only be >= 0
  74. 0:    tstw    sp@+        | result should be negative ?
  75.     bpl    0f
  76.     negl    d0        | yes, negate it
  77. 0:
  78.     movel    a1,d3
  79.     movel    a0,d2
  80.     rts
  81. 9:
  82.     divu    d2,d1        | cause division trap
  83.     bra    8b        | back to user
  84.  
  85.  
  86. __modsi3:
  87. ___modsi3:
  88.     movel    sp@(8),sp@-    | push divisor
  89.     movel    sp@(8),sp@-    | push dividend
  90.     jbsr    __divsi3
  91.     addql    #8,sp
  92.     movel    d1,d0        | return the remainder in d0
  93.     rts
  94.